package com.smart.service.impl;

import java.util.*;

import com.smart.vo.AppUserVo;
import com.smart.entity.SysCar;
import com.smart.entity.SysUser;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;

import com.smart.mapper.UserMapper;
import cn.hutool.core.util.StrUtil;

import com.smart.service.CarService;
import com.smart.service.UserService;
import com.smart.util.SysUserUtils;
import com.smart.service.RoleService;
import com.smart.service.OnlineUserService;
import com.smart.common.utils.JwtTokenUtil;
import com.smart.common.utils.SecurityUtils;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;

import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.security.core.userdetails.UserDetails;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

/**
 * @author lgb
 * @date 2020年6月9日 上午11:36:47
 * Copyright (C) 深圳工勘科技
 * @说明: 用户管理
 **/
@Slf4j
@Service("sysUserService")
public class UserServiceImpl extends BaseServiceImpl<SysUser, Long> implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RoleService roleService;
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private OnlineUserService onlineUserService;

    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private CarService carService;

    /**
     * (non-Javadoc)
     *
     * @see:
     **/
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public AppUserVo login(String un, String pwd, HttpServletRequest req) {
        AppUserVo vo = verUserDetails(un, pwd, req);
        // 密码需要客户端加密后传递
        boolean singleLogin = false;
        if (singleLogin) {//踢掉之前已经登录的token
            SysUser details = SysUserUtils.getSysUser();
            onlineUserService.checkLoginOnUser(details.getUsername(), vo.getToken());
        }
        return vo;
    }

    @Override
    @Transactional(readOnly = true)
    public AppUserVo appLogin(String un, String pwd, HttpServletRequest req) {
        return verUserDetails(un, pwd, req);
    }

    /**
     * (non-Javadoc)
     *
     * @see: 根据用户名获取用户
     **/
    @Override
    @Transactional(readOnly = true)
    public SysUser getByUserName(String username) {
        return this.baseMapper.selectOne(
                new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
    }

    /**
     * @param un  用户名
     * @param pwd 密码
     * @return 根据用户名与密码验证用户详情
     **/
    private AppUserVo verUserDetails(String un, String pwd, HttpServletRequest req) {
        AppUserVo vo = new AppUserVo();
        UserDetails userDetails = userDetailsService.loadUserByUsername(un);
        if (!passwordEncoder.matches(pwd, userDetails.getPassword())) {
            throw new BadCredentialsException("密码不正确");
        }
        UsernamePasswordAuthenticationToken authentication =
                new UsernamePasswordAuthenticationToken(userDetails, null,
                        userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String token = jwtTokenUtil.generateToken(userDetails.getUsername());
        SysUser details = SysUserUtils.getSysUser();
        try {
            BeanUtils.copyProperties(vo, details);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            log.warn("登录异常:{}", e.getMessage());
        }
        vo.setToken(token);
        vo.setTokenHead(jwtTokenUtil.getTokenHead());
        vo.setExpiration(jwtTokenUtil.getExpiration());
        Map<String, Object> roleData = new HashMap<String, Object>();
        roleData.put("roleId", details.getRoleId());
        roleData.put("roleName", details.getRoleName());
        vo.setSysRole(roleData);
        /** 查询当前用户的车辆情况(包括设备信息) */
        Map<String, Object> car = carService.getCarListByUserId(details.getId());
        vo.setSysCar(car);
        /** 用户信息 */
        vo.setSysUser(details);
        return vo;
    }

    /**
     * (non-Javadoc)
     *
     * @see: 修改密码
     **/
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int updatePasswordByUserId(Long userId, String newPassword) {
        SysUser user = new SysUser();
        user.setPassword(newPassword);
        user.setId(userId);
        return this.baseMapper.updateById(user);
    }

    @Override
    @Transactional(readOnly = true)
    public IPage<SysUser> getPage(Map<String, Object> params) {
        SysUser sysUser = SysUserUtils.getSysUser();
        int pageSize = Integer.parseInt(String.valueOf(params.get("pageSize")));
        int pageNum = Integer.parseInt(String.valueOf(params.get("pageNum")));
        String username = (String) params.get("username");
        String phone = (String) params.get("phone");
        String deptId = (String) params.get("deptId");
        String beginTime = (String) params.get("beginTime");
        String endTime = (String) params.get("endTime");
        String status = (String) params.get("status");
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotEmpty(username)) {
            wrapper.like(SysUser::getUsername, username);
        }
        if (StrUtil.isNotEmpty(phone)) {
            wrapper.like(SysUser::getPhone, phone);
        }
        if (StrUtil.isNotEmpty(deptId)) {
            wrapper.apply("(dept_id = " + deptId + " OR dept_id IN ( SELECT t.id FROM sys_dept t WHERE FIND_IN_SET ( " + deptId + " , ancestors ) ))");
        }
        if (StrUtil.isNotEmpty(beginTime)) {
            wrapper.gt(SysUser::getCreateTime, beginTime);
        }
        if (StrUtil.isNotEmpty(endTime)) {
            wrapper.lt(SysUser::getCreateTime, endTime);
        }
        if (StrUtil.isNotEmpty(status)) {
            wrapper.eq(SysUser::getStatus, status);
        }
        if (SecurityUtils.isAdmin(sysUser.getId())) {
            wrapper.notIn(SysUser::getId, 1);
        } else {
            wrapper.notIn(SysUser::getId, 1, sysUser.getId());
        }

        wrapper.apply(params.get("sql_filter") != null, (String) params.get("sql_filter"));
        return page(new Page<>(pageNum, pageSize), wrapper);
    }

    /**
     * (non-Javadoc)
     *
     * @see: 创建用户及权限
     **/
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int insertUserAndRole(SysUser user, String carNo) {
        List<Long> roleIds = new ArrayList<>();

        roleIds.add(user.getRoleId());    //改为一个用户对应一个角色
        System.err.println("收到：" + user.getRoleId());
        user.setRoleId(roleIds.get(0));
        user.setRoleName(roleService.findById(roleIds.get(0)).getName());
        int result = this.baseMapper.insert(user);
        if (roleIds.get(0).intValue() == 3) {//表示司机
            List<SysCar> carList = carService.findCarByNo(carNo);
            if (carList.isEmpty()) {

            }
        }
        //保存用户与角色关系
        userMapper.insertUserAndUserRole(user.getId(), roleIds);
        return result;
    }

    /**
     * (non-Javadoc)
     *
     * @see: 修改用户
     **/
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int updateUser(SysUser user, String carNo) {

        List<Long> roleIds = new ArrayList<>();

        roleIds.add(user.getRoleIds());
        ;//改为一个用户对应一个角色
        //第一步修改用户基本表
        boolean result = updateById(user);
        //删除之前的用户角色对应关系
        userMapper.deleteUserAndUserRole(user.getId());
        //从新插入用户与角色对应关系
        userMapper.insertUserAndUserRole(user.getId(), roleIds);
        return result == true ? 1 : 0;
    }

    @Override
    public int deleteByIds(Long[] ids) {
        return this.baseMapper.deleteBatchIds(Arrays.asList(ids));
    }

    @Override
    @Transactional(readOnly = true)
    public String findNameByUserId(Long roleId) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUser::getRoleId, roleId).eq(SysUser::getValid, 1);
        String str = "";
        List<SysUser> list = userMapper.selectList(wrapper);
        if (!list.isEmpty()) {
            for (SysUser user : list) {
                str += user.getNickName() + ",";
            }
        }
        return str;
    }

}